﻿//_______________________________________________________________________________________________________________________
// Copy Right (c) 2010, 2011 SapiensIT Consulting GmbH, all rights reserved
//_______________________________________________________________________________________________________________________
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT
// NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//_______________________________________________________________________________________________________________________
// PROJECT:     sapiens.at.SharePoint.QueryBuilder (SharePoint 2010/V4)
//_______________________________________________________________________________________________________________________
// VERSION:     2.0
//_______________________________________________________________________________________________________________________
// DESCRIPTION: 
//_______________________________________________________________________________________________________________________
// LICENSE:     Different licens Types apply to different file types:
//               - Source code files are governed by the MICROSOFT PUBLIC LICENSE (Ms-PL)
//               - Binary files are governed by MSDN CODE GALLERY BINARY LICENSE
//               - Documentation files are governed by CREATIVE COMMONS ATTRIBUTION 3.0 LICENSE
//
//               The licenses can be found at the projects source location.
//               If you do not agree, don't use it!
// 
//_______________________________________________________________________________________________________________________
// Start SharePoint Branding, visit http://www.cliggin.com! Visit us on http://www.sapiens.at! Tell your friends! 
//_______________________________________________________________________________________________________________________
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Sapiens.at.SharePoint.Utils
{
    /// <summary>
    /// Represents either an Or or an And operator.
    /// </summary>
    /// <remarks>
    /// The result of this expression is depending on the number of expressions to combine. If there is no expression, the <see cref="ToString"/> returns
    /// and empty string. If there is only one expression, it returns the result of <see cref="IQueryBuilderExpression.ToString"/> of the expression.
    /// For exact two expressions the operator creates the standard CAML <c>&lt;And&gt;&lt;Exp1 /&gt;&lt;Exp2 /&gt;&lt;/And&gt;</c>. If there are more then
    /// two expressions, they will be nested.
    /// </remarks>
    /// <seealso cref="QueryBuilder"/>
    public class QueryBuilderConnective : IQueryBuilderExpression
    {
        string _type;
        List<IQueryBuilderExpression> _exps;

        /// <summary>
        /// Instantiates a new operator.
        /// </summary>
        /// <param name="type">Either "Or" or "And"</param>
        /// <param name="expressions">A collection of expressions to combine</param>
        public QueryBuilderConnective(string type, params IQueryBuilderExpression[] expressions)
        {
            // only "And" or "Or" si allowed
            if (type != "And" && type != "Or") { throw new ArgumentException("Unknown container type '" + type + "'", "type"); }

            _type = type;
            _exps = new List<IQueryBuilderExpression>(expressions);
        }

        /// <summary>
        /// Add an expression to the operator
        /// </summary>
        /// <param name="exp">The expression to add</param>
        public void Add(IQueryBuilderExpression exp)
        {
            _exps.Add(exp);
        }

        /// <summary>
        /// Converts the expression into the CAML representation.
        /// </summary>
        /// <returns>The CAML query for this expression</returns>
        public override string ToString()
        {
            var expressions = _exps.Where(exp => exp != null && !exp.IsEmpty()).ToArray();
            if (expressions.Length > 1)
            {
                var result = expressions.Last().ToString();
                for (int i = expressions.Length - 2; i >= 0; i--)
                {
                    result = string.Format("<{0}>{1}{2}</{0}>", _type, expressions[i].ToString(), result);
                }
                return result;
            }
            else if (expressions.Length == 1)
            {
                return expressions[0].ToString();
            }
            return string.Empty;
        }

        /// <summary>
        /// Determines, whether this expression is unimportant for the query.
        /// </summary>
        /// <returns>true, if this expression can be left out in the query; otherwise false</returns>
        public bool IsEmpty()
        {
            return _exps.All(exp => exp == null || exp.IsEmpty());
        }
    }
}
